﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WordNet.Core.Util;

namespace WordNet.Core.Extensions
{
    public static class WordNetExtensions
    {
        public static String StripUderscore(this String word)
        {
            return word.Replace("_", "");
        }
        
        public static String StripHyphen(this String word)
        {
            return word.Replace("-", "");
        }
        
        public static String StripPeriods(this String word)
        {
            return word.Replace(".", "");
        }
        
        public static String UnderscoreToHyphen(this String word)
        {
            return word.Replace('_', '-');
        }
       
        public static String HyphenToUnderscore(this String word)
        {
            return word.Replace('-', '_');
        }
        
        public static String ToWhitespace(this String word)
        {
            word = word.Replace('_', ' ');

            word = word.Replace('-', ' ');

            return word;
        }
        
        // Converts all whitespace runs to single underscores.
        public static String WhitespaceToUnderscore(this String word)
        {
            // replace all underscores with spaces
            word = word.Replace('_', ' ');

            // trim off extra whitespace
            word = word.Trim();
            if (word.Length == 0)
                throw new ArgumentException();

            // replace all whitespace with underscores
            word = word.Replace(' ', '_');

            // return normalized word
            return word;
        }
        
        
        public static void CheckLexicalFileNumber(this int num)
        {
            if (IsIllegalLexicalFileNumber(num))
                throw new ArgumentException(String.Format(Message.IllegalLexicalFileNumber, num));
        }

        public static bool IsIllegalLexicalFileNumber(this int num)
        {
            return num < Constants.FileNumberMin || Constants.FileNumberMax < num;
        }
        
        public static String GetLexicalFileNumberString(this int num)
        {
            CheckLexicalFileNumber(num);
            if (num < Constants.LexicalIDNumbers.Length)
                return Constants.LexicalIDNumbers[num];
            return num.ToString();
        }
        
        public static bool IsIllegalWordNumber(this int num)
        {
            if (num < Constants.WordNumberMin)
                return true;
            if (num > Constants.WordNumberMax)
                return true;
            return false;
        }

        public static bool IsIllegalLexicalID(this int id)
        {
            if (id < Constants.LexicalIDMin)
                return true;
            if (id > Constants.LexicalIDMax)
                return true;
            return false;
        }
       
        public static String GetLexicalIDForDataFile( this int lexID)
        {
            CheckLexicalID(lexID);
            return lexID.ToString("x"); // a single digit hex
        }

        public static string GetLexicalIDForSenseKey(this int lexID)
        {
            CheckLexicalID(lexID);
            return (lexID < Constants.LexicalIDNumbers.Length) ?
                  Constants.LexicalIDNumbers[lexID] :
                  lexID.ToString();// a two-digit decimal number
        }

        public static String ZeroFillWordNumber(this int num)
        {
            CheckWordNumber(num);
            StringBuilder sb = new StringBuilder(2);
            String str = num.ToString("x2");// a two hex digit
            int numZeros = 2 - str.Length;
            for (int i = 0; i < numZeros; i++)
                sb.Append('0');
            for (int i = 0; i < str.Length; i++)
                sb.Append(Char.ToUpper(str[i]));
            return sb.ToString();
        }

        public static String ZeroFillOffset(this int offset)
        {
            CheckOffset(offset);
            StringBuilder sb = new StringBuilder(8);
            String offsetStr = offset.ToString();
            int numZeros = 8 - offsetStr.Length;
            for (int i = 0; i < numZeros; i++)
                sb.Append('0');
            sb.Append(offsetStr);
            return sb.ToString();
        }

        public static int CheckOffset(this int offset)
        {
            if (!IsLegalOffset(offset))
                throw new ArgumentException(String.Format(Message.NotValidOffset, offset));
            return offset;
        }
        
        public static bool IsLegalOffset(this int offset)
        {
            if (offset < Constants.LegalOffsetMin)
                return false;
            if (offset > Constants.LegalOffsetMax)
                return false;
            return true;
        }

        public static bool IsAdjectiveSatellite(this int num)
        {
            return num == Constants.AdjectiveSatelliteNumber;
        }
       
        public static void CheckWordNumber(this int num)
        {
            if (num.IsIllegalWordNumber())
                throw new ArgumentException(String.Format(Message.IllegalWordNumber, num));
        }

        public static void CheckLexicalID(this int id)
        {
            if (id.IsIllegalLexicalID())
                throw new ArgumentException(String.Format(Message.IllegalLexicalID, id));
        }

        public static bool ContainsPattern(this String target, HashSet<string> patterns)
        {
            if (patterns == null || patterns.Count() == 0)
                return true;
            return patterns.Contains(target);
        }

        public static FileInfo Find<T>(this IDataType<T> type, POS pos, ICollection<FileInfo> files)
        {
            HashSet<String> typePatterns = type.GetResourceKeywords() as HashSet<String>;
            HashSet<String> posPatterns = pos.Hint;
            String name;
            foreach (FileInfo file in files)
            {
                name = file.FullName.ToLower();
                if (ContainsPattern(name, typePatterns) && ContainsPattern(name, posPatterns))
                    return file;
            }

            return null;
        }
    }
}
